package com.sumer.psychology.microblog.domain.model;

import com.sumer.psychology.common.Assert;
import com.sumer.psychology.common.domain.model.Author;
import com.sumer.psychology.common.domain.model.ConcurrencySafeEntity;

import java.util.Date;

/**
 * 微博
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/9/2
 * Time: 9:48
 */
public class MicroBlog extends ConcurrencySafeEntity {
    private MicroBlogId microBlogId;
    private String content;
    private Author author;
    private Date createTime;
    private Date lastModifyTime;
    private MicroBlogAvailability availability;

    /**
     * 创建微博
     *
     * @param microBlogId id
     * @param content     content
     * @param author      author
     */
    public MicroBlog(MicroBlogId microBlogId, String content, Author author) {
        setMicroBlogId(microBlogId);
        setContent(content);
        setAuthor(author);
        setCreateTime(new Date());
        setAvailability(MicroBlogAvailability.ACTIVE);

        apply(new MicroBlogCreatedEvent(
                microBlogId(),
                content(),
                author()));
    }

    public MicroBlog() {
    }

    /**
     * 删除微博
     */
    public void delete() {
        setAvailability(MicroBlogAvailability.DELETED);
        setLastModifyTime(new Date());

        apply(new MicroBlogDeletedEvent(microBlogId()));
    }

    private void setMicroBlogId(MicroBlogId microBlogId) {
        Assert.notNull(microBlogId, "id不能为空");
        Assert.notEmpty(microBlogId.identity(), "id不能为空");

        this.microBlogId = microBlogId;
    }

    private void setContent(String content) {
        Assert.notEmpty(content, "内容不能为空");
        Assert.length(content, 300, "内容长度不能超过150个字");

        this.content = content;
    }

    private void setAuthor(Author author) {
        Assert.notNull(author, "作者不能为空");
        Assert.notEmpty(author.identity(), "作者Id不能为空");

        this.author = author;
    }

    private void setCreateTime(Date createTime) {
        Assert.notNull(createTime, "创建日期不能为空");

        this.createTime = createTime;
    }

    private void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    private void setAvailability(MicroBlogAvailability availability) {
        Assert.notNull(availability, "状态不能为空");

        this.availability = availability;
    }

    public MicroBlogId microBlogId() {
        return microBlogId;
    }

    public String content() {
        return content;
    }

    public Author author() {
        return author;
    }

    public Date createTime() {
        return createTime;
    }

    public Date lastModifyTime() {
        return lastModifyTime;
    }

    public MicroBlogAvailability availability() {
        return availability;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MicroBlog microBlog = (MicroBlog) o;

        if (author != null ? !author.identity().equals(microBlog.author.identity()) : microBlog.author != null)
            return false;
        if (availability != microBlog.availability) return false;
        if (content != null ? !content.equals(microBlog.content) : microBlog.content != null) return false;
        if (microBlogId != null ? !microBlogId.equals(microBlog.microBlogId) : microBlog.microBlogId != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = microBlogId != null ? microBlogId.hashCode() : 0;
        result = 31 * result + (content != null ? content.hashCode() : 0);
        result = 31 * result + (author != null ? author.identity().hashCode() : 0);
        result = 31 * result + (availability != null ? availability.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "MicroBlog{" +
                "microBlogId=" + microBlogId +
                ", content='" + content + '\'' +
                ", author=" + author +
                ", createTime=" + createTime +
                ", lastModifyTime=" + lastModifyTime +
                ", availability=" + availability +
                '}';
    }
}
